package org.hk.proxy.server.container;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.socksx.v5.Socks5CommandRequestDecoder;
import io.netty.handler.codec.socksx.v5.Socks5InitialRequestDecoder;
import io.netty.handler.codec.socksx.v5.Socks5ServerEncoder;
import org.hk.proxy.common.container.Container;
import org.hk.proxy.common.container.ContainerHelper;
import org.hk.proxy.server.channel.ProxyChannelManager;
import org.hk.proxy.server.handlers.Socks5CommandRequestInboundHandler;
import org.hk.proxy.server.handlers.Socks5InitialRequestInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutionException;

public class ProxySocket5Container extends ContainerHelper implements Container {
    public static final Logger log = LoggerFactory.getLogger(ProxySocket5Container.class);
    private NioEventLoopGroup serverWorkerGroup;
    private NioEventLoopGroup serverBossGroup;
    public ProxySocket5Container() {
        serverBossGroup = new NioEventLoopGroup(4);
        serverWorkerGroup = new NioEventLoopGroup(8);
    }
    @Override
    public void start() throws ExecutionException, InterruptedException {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(serverBossGroup,serverWorkerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch){
                ChannelPipeline pipeline =  ch.pipeline();
                //socks5响应最后一个encode
                pipeline.addLast(Socks5ServerEncoder.DEFAULT);
                //处理socks5初始化请求
                pipeline.addLast(new Socks5InitialRequestDecoder());
                pipeline.addLast(new Socks5InitialRequestInboundHandler());
                pipeline.addLast(new Socks5CommandRequestDecoder());
                pipeline.addLast(new Socks5CommandRequestInboundHandler());
            }
        });
        for(int port: ProxyChannelManager.clientKeyServerPort.keySet()){
            serverBootstrap.bind(new InetSocketAddress(port));
        }
    }
    @Override
    public void stop() {
        serverBossGroup.shutdownGracefully();
        serverWorkerGroup.shutdownGracefully();
    }
}
